package com.gpc.hexapods.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.gpc.hexapods.R;
import com.gpc.hexapods.gl.GLView;
import com.gpc.hexapods.gl.GlListener;
import com.gpc.hexapods.layer.ControlLayout;
import com.gpc.hexapods.service.BluetoothChatService;
import com.gpc.hexapods.utils.Utils;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity implements GlListener {

    private static final String TAG = "MainActivity";

    private static final String ADDRESS = "20:21:04:19:45:73";

    public static final String DEVICE_NAME = "device_name";

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static final String[] PERMISSIONS_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE };

    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;

    private static final int REQUEST_CONNECT_DEVICE = 1;
    private static final int REQUEST_ENABLE_BT = 2;

    private TextView mTitleView;
    private TextView mVolView;
    private GLView mGLView;
    private ControlLayout mControlLayout;
    private Vibrator mVibrator;
    private String mDeviceName;

    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothChatService mChatService;
    private ChatHandler mChatHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTitleView = findViewById(R.id.title);
        mVolView = findViewById(R.id.vol);
        mControlLayout = findViewById(R.id.control_layout);
        mGLView = (GLView) findViewById(R.id.glView);

        mGLView.setListener(this);
        mControlLayout.setCtrlListener(mGLView);

        mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mChatHandler = new ChatHandler(new WeakReference<>(this));
        mChatService = new BluetoothChatService(this, mChatHandler);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        }
    }

    public void onDev(View view) {
        startActivity(new Intent(this, BluetoothChat.class));
    }

    public void onScan(View view) {
        mVibrator.vibrate(50);
        if (mChatService != null && mChatService.getState() == BluetoothChatService.STATE_CONNECTED) {
            mChatService.stop();
        } else {
            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(ADDRESS);
            mChatService.connect(device);
        }
    }

    public void onPower(View view) {
        mVibrator.vibrate(50);
        sendMessage(0x71, 1);
        try {
            Thread.sleep(200);
        } catch (Exception e) {

        }
        sendMessage(0x81, 0);
    }

    private void sendMessage(int cmd, int value) {
        byte[] send = new byte[6];
        send[0] = (byte) 0xFF;
        send[1] = (byte) cmd;
        send[2] = (byte) value;
        send[3] = Utils.crc(send);
        send[4] = (byte) 0xFD;
        send[5] = (byte) 0xFE;
        mChatService.write(send);
    }

    @Override
    public void sendArray(short[] value) {
        byte cmd = (byte) 0xA0;
        Log.i(TAG, "sendArray -> input : " + Arrays.toString(value));
        byte[] array = Utils.shortToByte(value);
        //Log.i(TAG, "sendArray -> output : " + Arrays.toString(array));
        int[] temp = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            temp[i] = array[i] & 0xFF;
        }
        Log.i(TAG, "sendArray -> output : " + Arrays.toString(temp));
        int size = array.length + 5;
        byte[] send = new byte[size];
        send[0] = (byte) 0xFF;
        send[1] = (byte) cmd;
        System.arraycopy(array, 0, send, 2, array.length);
        send[size - 3] = Utils.crc(send);
        send[size - 2] = (byte) 0xFD;
        send[size - 1] = (byte) 0xFE;
        //Log.i(TAG, "sendArray -> send : " + Arrays.toString(send));
        int[] end = new int[send.length];
        String[] list = new String[send.length];
        for (int i = 0; i < send.length; i++) {
            end[i] = send[i] & 0xFF;
            list[i] = Integer.toHexString(end[i]);
        }
        Log.i(TAG, "sendArray -> send : " + Arrays.toString(end));
        Log.i(TAG, "sendArray -> list : " + Arrays.toString(list));
        mChatService.write(send);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mGLView.setListener(null);
        if (mChatService != null) {
            mChatService.stop();
        }
    }

    private static class ChatHandler extends Handler {

        private WeakReference<MainActivity> mActivity;

        ChatHandler(WeakReference<MainActivity> activity) {
            mActivity = activity;
        }

        @SuppressLint("SetTextI18n")
        @Override
        public void handleMessage(@NonNull Message msg) {
            MainActivity activity = mActivity.get();
            if (activity == null) {
                return;
            }
            switch (msg.what) {
                case MESSAGE_STATE_CHANGE:
                    Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                    switch (msg.arg1) {
                        case BluetoothChatService.STATE_CONNECTED:
                            activity.mTitleView.setText(R.string.title_connected_to);
                            break;
                        case BluetoothChatService.STATE_CONNECTING:
                            activity.mTitleView.setText(R.string.title_connecting);
                            activity.mVolView.setText("");
                            break;
                        case BluetoothChatService.STATE_LISTEN:
                        case BluetoothChatService.STATE_NONE:
                            activity.mTitleView.setText(R.string.title_not_connected);
                            activity.mVolView.setText("");
                            break;
                    }
                    break;

                case MESSAGE_READ:
                    byte[] readBuf = (byte[]) msg.obj;
                    String readMessage = new String(readBuf, 0, msg.arg1);
                    Log.i(TAG, "readMessage : " + readMessage);
                    if (!TextUtils.isEmpty(readMessage) && readMessage.startsWith("vol : ")) {
                        String vol = readMessage.substring(6, readMessage.length() - 1);
                        try {
                            BigDecimal value = BigDecimal.valueOf((Integer.parseInt(vol) / 1000f))
                                    .setScale(2, BigDecimal.ROUND_HALF_UP);
                            activity.mVolView.setText(value + "V");
                        } catch (NumberFormatException e) {
                            activity.mVolView.setText(vol);
                        }
                    }
                    break;

                case MESSAGE_DEVICE_NAME:
                    activity.mDeviceName = msg.getData().getString(DEVICE_NAME);
                    Toast.makeText(activity.getApplicationContext(), "Connected to "
                            + activity.mDeviceName, Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }
}